package com.baiyang.server.config.provider;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import com.baiyang.server.model.system.User;
import com.baiyang.server.model.system.UserRole;
import com.baiyang.server.service.system.UserRoleService;
import com.baiyang.server.service.system.UserService;
import com.baiyang.server.tools.Data;
import com.baiyang.server.tools.DataTool;
import org.springframework.util.DigestUtils;

/**
 * 自定义认证过程
 *
 * @author XVX
 */
@Component
public class MyAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    @Autowired
    private UserService userService = null;
    @Autowired
    private UserRoleService userRoleService = null;
    @Autowired
    private PasswordEncoder passwordEncoder = null;

    /**
     * 附加认证过程  --  进行用户信息认证
     */
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
                                                  UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        // TODO Auto-generated method stub
        System.out.println("附加认证过程");
        if (authentication.getCredentials() == null) {
            logger.debug("Authentication failed: no credentials provided");

            throw new BadCredentialsException(messages.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials",
                    "Bad credentials"));
        }

        String presentedPassword = authentication.getCredentials().toString();
        // rawPassword--原始密码    encodedPassword--被加密后的密码
        if (!passwordEncoder.matches(presentedPassword, passwordEncoder.encode(userDetails.getPassword()))) {

            throw new BadCredentialsException(messages.getMessage(
                    "MyAuthenticationProvider.badCredentials",
                    Data.ERROR.PASSWORD));
        }
    }

    /**
     * @apiNote 获取用户信息 首先判断该用户是否存在，然后根据用户角色进行判断具体验证方式
     * @author XVX
     * @version 1
     * @since 2021-11-18
     */
    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        // TODO Auto-generated method stub
        User user = new User();
        user.setUserName(username);
        user = userService.selectOneByUserName(username);
        UserDetail detail = new UserDetail();
        if (user != null) {
            List<UserRole> userRoles = userRoleService.selectByUserId(user.getId());
            if (userRoles != null && userRoles.size() != 0) {
                // 如果是读者则不进行验证码判断
                if (isReader(userRoles)) {

                }else{
                    MyUsernamePasswordAuthenticationToken authenticationToken = (MyUsernamePasswordAuthenticationToken) authentication;
                    MyWebAuthenticationDetails authenticationDetails = (MyWebAuthenticationDetails) authentication.getDetails();
                    HttpSession session = authenticationDetails.getSession();
                    if (session == null) {
                        throw new BadCredentialsException(messages.getMessage("MyAuthenticationProvider.badCredentials",
                                Data.ERROR.VERCODE));
                    }
                    Object ver = session.getAttribute(Data.Session.VER_CODE);
                    String verCode = ver == null ? "" : String.valueOf(ver);
                    if (DataTool.isBlank(verCode) || DataTool.isBlank(authenticationToken.getVerCode()) || !verCode.equals(authenticationToken.getVerCode())) {
                        throw new BadCredentialsException(messages.getMessage("MyAuthenticationProvider.badCredentials",
                                Data.ERROR.VERCODE));
                    }
                    session.removeAttribute(Data.Session.VER_CODE);
                }
                /**
                 * 配置用户权限
                 * todo
                 */
                List<Authority> authorities = new ArrayList<Authority>();
                //根据用户角色获取访问权限
                userRoles.forEach(e -> {
                    Authority authority = new Authority(e.getRoleId());
                    authorities.add(authority);
                });
                detail.setAuthorities(authorities);
            }
            detail.setUserName(user.getUserName());
            detail.setPassword(user.getPassword());
            detail.setUser(user);
        } else {
            throw new BadCredentialsException(messages.getMessage("MyAuthenticationProvider.badCredentials",
                    Data.ERROR.USERNAME));
        }
        return detail;
    }

    /**
     * @param userRoles
     * @return
     * @apiNote 判断用户是否是管理员
     */
    private boolean isAdmin(List<UserRole> userRoles) {
        for (UserRole userRole : userRoles) {
            if (Data.DataDictionary.SUPER_ADMIN_ROLE_ID.equals(userRole.getRoleId())) {
                return true;
            }
        }
        return false;
    }

    private boolean isReader(List<UserRole> userRoles) {
        for (UserRole userRole : userRoles) {
            if (Data.DataDictionary.READER_ROLE_ID.equals(userRole.getRoleId())) {
                return true;
            }
        }
        return false;
    }

}
